package ua.maxicash.dao;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import ua.maxicash.vo.Message;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;

@Repository("messageDao")
public class MessageDaoImpl implements MessageDao {

    @Autowired
    HibernateTemplate hibernateTemplate;

    @Override
    @Transactional
    public void saveMessage(Message message) {
        hibernateTemplate.saveOrUpdate(message);
    }

    @Override
    public List<Message> listMessages() {
        return hibernateTemplate.findByCriteria(DetachedCriteria.forClass(Message.class));
    }

    @Override
    @Transactional
    public List<Message> getAllReceivedMessages(String receiversEmail) {

        DetachedCriteria criteria = DetachedCriteria.forClass(Message.class);
        DetachedCriteria recCrit = criteria.createCriteria("receiver");
        recCrit.add(Restrictions.eq("email", receiversEmail));
        return hibernateTemplate.findByCriteria(recCrit);

    }

    @Override
    public List<Message> getAllSentMessages(String sendersEmail) {

        DetachedCriteria criteria = DetachedCriteria.forClass(Message.class);
        DetachedCriteria sendCrit = criteria.createCriteria("sender");
        sendCrit.add(Restrictions.eq("email", sendersEmail));
        return hibernateTemplate.findByCriteria(sendCrit);
        
    }

    @Override
    public long getCountOfUnreadMessages(String userEmail) {
        
    	DetachedCriteria criteria = DetachedCriteria.forClass(Message.class);
    	criteria.createCriteria("receiver").add(Restrictions.eq("email", userEmail));
    	criteria.add(Restrictions.eq("read",false));
    	criteria.setProjection(Projections.rowCount());
        return ((Long)hibernateTemplate.findByCriteria(criteria).get(0));
        
        
    }

    @Override
    @Transactional
    public Message getMessageById(Long idMessage, boolean markAsRead) {

        Message message = (Message) DataAccessUtils.uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(Message.class).add(Restrictions.idEq(idMessage))));
        message.getText();
        
        if (markAsRead && !message.isRead()) {
        	markMessageAsRead(idMessage);
        }
        return message;
    }

    @Override
    @Transactional
    public void markMessageAsRead(Long idMessage) {

        Message message = (Message) DataAccessUtils.uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(Message.class).add(Restrictions.idEq(idMessage))));
        message.setRead(true);
        hibernateTemplate.merge(message);

    }

    @Override
    @Transactional
    public Set<Message> getReceivedMessages(Long idReceiver, Long offset, Long amount){

        Session session = hibernateTemplate.getSessionFactory().getCurrentSession();
        Query query = session.createQuery("from Message as m where m.receiver = :idReceiver order by m.time desc");
        query.setFirstResult(offset.intValue()-1);
        query.setMaxResults(amount.intValue());
        query.setLong("idReceiver",idReceiver);

        return new TreeSet<Message>(query.list());

    }

    @Override
    @Transactional
    public Set<Message> getSentMessages(Long idSender, Long offset, Long amount){
        Session session = hibernateTemplate.getSessionFactory().getCurrentSession();
        Query query = session.createQuery("from Message as m where m.sender = :idSender order by m.time desc");
        query.setFirstResult(offset.intValue() - 1);
        query.setMaxResults(amount.intValue());
        query.setLong("idSender", idSender);

        return new TreeSet<Message>(query.list());
    }

    @Override
    public long getCountOfReceivedMessages(String receiversEmail) {
        DetachedCriteria criteria = DetachedCriteria.forClass(Message.class);
        DetachedCriteria recCrit = criteria.createCriteria("receiver");
        recCrit.add(Restrictions.eq("email", receiversEmail));
        recCrit.setProjection(Projections.rowCount());

        return (Long)hibernateTemplate.findByCriteria(recCrit).get(0);

    }

    @Override
    public long getCountOfSentMessages(String sendersEmail) {
        DetachedCriteria criteria = DetachedCriteria.forClass(Message.class);
        DetachedCriteria recCrit = criteria.createCriteria("sender");
        recCrit.add(Restrictions.eq("email", sendersEmail));
        recCrit.setProjection(Projections.rowCount());

        return (Long)hibernateTemplate.findByCriteria(recCrit).get(0);
    }

}
